/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.business.service.impl;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.business.domain.Hljg;
import me.zhengjie.business.domain.HljgTc;
import me.zhengjie.business.domain.Snry;
import me.zhengjie.business.domain.Zhsq;
import me.zhengjie.business.domain.sup.Gsgl;
import me.zhengjie.business.domain.vo.HljgDistance;
import me.zhengjie.business.domain.vo.HljgDspVo;
import me.zhengjie.business.repository.*;
import me.zhengjie.domain.vo.TableInfo;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.repository.DeptRepository;
import me.zhengjie.modules.system.repository.UserRepository;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.business.service.HljgService;
import me.zhengjie.business.service.dto.HljgDto;
import me.zhengjie.business.service.dto.HljgQueryCriteria;
import me.zhengjie.business.service.mapstruct.HljgMapper;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.util.StringUtils;

import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author xiahongbo
* @date 2022-04-12
**/
@Slf4j
@Service
@RequiredArgsConstructor
public class HljgServiceImpl implements HljgService {

    private final PasswordEncoder passwordEncoder;
    private final UserRepository userRepository;
    private final HljgRepository hljgRepository;
    private final HljgTcRepository hljgTcRepository;
    private final SbgsRepository sbgsRepository;
    private final GsglRepository gsglRepository;
    private final HljgMapper hljgMapper;
    private final ZhsqRepository zhsqRepository;
    private final SnryRepository snryRepository;
    @PersistenceContext
    private EntityManager em;

    private final DeptRepository deptRepository;
    private final RedisUtils redisUtils;

    @Override
    public Map<String,Object> queryAll(HljgQueryCriteria criteria, Pageable pageable){
        Page<Hljg> page = hljgRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        log.info("HljgServiceImpl queryAll page : {} ", PageUtil.toPage(page.map(hljgMapper::toDto)));
        return PageUtil.toPage(page.map(hljgMapper::toDto));
    }

    @Override
    public Object queryTodo(String name, String sbgsId, int[] startEnd) {
        log.info("queryTodo startEnd : {} ", startEnd);
        // 使用预编译防止sql注入
        String sql = "SELECT R1.BIS_GSGL_ID, R1.BIS_GSGL_QYMC,R1.BIS_GSGL_YLJGDM, " +
                "sum(case when r2.BIS_ZHSQ_ZT = '01' then 1 else 0 end ) DFP_COUNT, " +
                "sum(case when (r2.BIS_ZHSQ_ZT = '02' or r2.BIS_ZHSQ_ZT = '03') then 1 else 0 end ) YFP_COUNT " +
                "FROM BIS_GSGL R1 " +
                "LEFT JOIN BIS_ZHSQ R2 ON R1.BIS_GSGL_ID=R2.BIS_ZHSQ_HLJG_ID and r2.BIS_PGGS_ID=:sbgsId AND R2.BIS_ZHSQ_ZHLB='01' " +
                "WHERE (R1.BIS_GSGL_SBGS_ID = :sbgsId OR R1.BIS_GSGL_PGGS_ID=:sbgsId OR R1.BZ like :pggsId) " +
                "group by R1.BIS_GSGL_ID,R1.BIS_GSGL_YLJGDM, R1.BIS_GSGL_QYMC " +
                "order by R1.BIS_GSGL_YLJGDM";
        Query query = em.createNativeQuery(sql);
        query.setFirstResult(startEnd[0]);
        query.setMaxResults(startEnd[1] - startEnd[0]);
        query.setParameter("sbgsId", sbgsId);
        query.setParameter("pggsId", "%" + sbgsId + "%");
        List result = query.getResultList();
        List<HljgDspVo> hljgDspVos = new ArrayList<>();
        for (Object obj : result) {
            Object[] arr = (Object[]) obj;
            log.info("queryTodo DFP_COUNT : {} ", arr[3]);
            hljgDspVos.add(new HljgDspVo(arr[0], arr[1], arr[2], arr[3].toString(), arr[4].toString()));
        }
        String countSql = "select count(BIS_GSGL_ID) from( " +
                "SELECT R1.BIS_GSGL_ID " +
                "FROM BIS_GSGL R1 " +
                "LEFT JOIN BIS_ZHSQ R2 ON R1.BIS_GSGL_ID=R2.BIS_ZHSQ_HLJG_ID and r2.BIS_PGGS_ID=:sbgsId " +
                "WHERE (R1.BIS_GSGL_SBGS_ID = :sbgsId OR R1.BIS_GSGL_PGGS_ID=:sbgsId OR R1.BZ like :pggsId) " +
                "group by R1.BIS_GSGL_ID)";
        Query queryCount = em.createNativeQuery(countSql);
        queryCount.setParameter("sbgsId", sbgsId);
        queryCount.setParameter("pggsId", "%" + sbgsId + "%");
        Object totalElements = queryCount.getSingleResult();
        Map<String,Object> m = PageUtil.toPage(hljgDspVos, totalElements);
        log.info("queryTodo m : {} ", m);
        return m;
    }

    @Override
    public List<HljgDto> queryAll(HljgQueryCriteria criteria){
        return hljgMapper.toDto(hljgRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    public List<HljgDto> queryMpAll(HljgQueryCriteria criteria){
        List<HljgDto> list = hljgMapper.toDto(hljgRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));

        Snry snry = snryRepository.findById(criteria.getBisSnryId()).get();
        if(StringUtils.isEmpty(snry.getBisSnryJd()) || StringUtils.isEmpty(snry.getBisSnryWd())) {

            for (HljgDto hljgDto: list) {
                hljgDto.setDistance("0公里");
                hljgDto.setSortDistance(0.00);
            }
        } else {
            double snryLongitude = Double.parseDouble(snry.getBisSnryJd());
            double snryLatitude = Double.parseDouble(snry.getBisSnryWd());

            for (HljgDto hljgDto: list) {
                double hljgLongitude =Double.parseDouble(hljgDto.getBisGsglJd());
                double hljgLatitude = Double.parseDouble(hljgDto.getBisGsglWd());
                Map<String, String> map = DistanceUtil.getDistance(snryLongitude, snryLatitude, hljgLongitude, hljgLatitude);
                double distance = Double.parseDouble(map.get("meter"));
                double kilometer = Double.parseDouble(map.get("kilometer"));
                hljgDto.setDistance(kilometer+"公里");
                hljgDto.setSortDistance(distance);
            }
            Collections.sort(list,new HljgDistance());
        }
        return list;
    }

    @Override
    public Hljg findByBisGsglUserId(Long bisGsglUserId) {
        return hljgRepository.findByBisGsglUserId(bisGsglUserId);
    }

    @Override
    @Transactional
    public HljgDto findById(String bisGsglId) {
        Hljg hljg = hljgRepository.findById(bisGsglId).orElseGet(Hljg::new);
        ValidationUtil.isNull(hljg.getBisGsglId(),"Hljg","bisGsglId",bisGsglId);
        return hljgMapper.toDto(hljg);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HljgDto create(Hljg resources) {
        log.info("HljgServiceImpl create Hljg : {} ", resources);

        // 新增护理机构，需要模拟用户插入
        User user = new User();
        user.setUsername(resources.getBisGsglYljgdm());
        user.setPassword(passwordEncoder.encode(DefaultUtil.PASSWORD));
        user.setNickName(resources.getBisGsglQymc());
        user.setPhone(resources.getBisGsglLxrdh());
        user.setEnabled(true);
        user.setIsAdmin(false);

        // 新增用户，模拟护理机构部门

        // 新增用户，模拟商保公司部门
        Dept dept = new Dept();
        dept.setPid(DefaultUtil.DEPT_HL);
        dept.setName(resources.getBisGsglQymc());
        dept.setEnabled(true);
        dept.setDeptSort(999);
        Dept newDept = deptRepository.save(dept);

        dept.setSubCount(0);
        // 计算子节点数目
        int count = deptRepository.countByPid(DefaultUtil.DEPT_HL);
        deptRepository.updateSubCntById(count, DefaultUtil.DEPT_HL);
        user.setDept(newDept);

        List<User> users = userRepository.findByRoleDeptId(DefaultUtil.DEPT_SB);
        // 删除数据权限
        redisUtils.delByKeys(CacheKey.DATA_USER, users.stream().map(User::getId).collect(Collectors.toSet()));
        redisUtils.del(CacheKey.DEPT_ID + DefaultUtil.DEPT_SB);


        // 新增用户，模拟护理机构角色
        Set<Role> setRole = new HashSet<Role>();
        Role role = new Role();


        if("02".equals(resources.getBisGsglChjgddfwlx())) {
            role.setId(DefaultUtil.ROLE_JGHL);
        } else if("01".equals(resources.getBisGsglChjgddfwlx())) {
            role.setId(DefaultUtil.ROLE_HL);
        }
        setRole.add(role);
        user.setRoles(setRole);

        user = userRepository.save(user);

        // 新增护理机构
        resources.setBisGsglId(IdUtil.simpleUUID());
        resources.setBisGsglUserId(newDept.getId());


        return hljgMapper.toDto(hljgRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Hljg resources) {
        Hljg hljg = hljgRepository.findById(resources.getBisGsglId()).orElseGet(Hljg::new);
    //    ValidationUtil.isNull( hljg.getBisHljgId(),"Hljg","BIS_HLJG_ID",resources.getBisHljgId());
        hljg.copy(resources);
    /*    if(StringUtils.isEmpty(resources.getSbgs().getBisSbgsId())) {
            Sbgs sbgs = sbgsRepository.findById(resources.getSbgs().getBisSbgsId()).orElseGet(Sbgs::new);
            hljg.setSbgs(sbgs);
        }*/
    //    user.setRoles(resources.getRoles());
        hljgRepository.save(hljg);

    }

    @Override
    public void deleteAll(String[] ids) {
        for (String bisHljgId : ids) {
            hljgRepository.deleteById(bisHljgId);
        }
    }

    @Override
    public void download(List<HljgDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (HljgDto hljg : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}